/**
 * COPYRIGHT. Harry Wu 2011. ALL RIGHTS RESERVED.
 * Project: just
 * Author: Harry Wu <harrywu304@gmail.com>
 * Created On: Jun 12, 2011 4:54:08 PM
 *
*/ 
package org.justframework.server;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.justframework.core.helper.ConfigHelper;
import org.justframework.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * locate resource through path match
 *
 */
public class ResourceLocator {
	/**
	 * logger
	 */
	private static Logger logger = LoggerFactory.getLogger(ResourceLocator.class);
	
	/**
	 * path template and resource class mapping
	 */
	private static Map<String,String> routeMap = new HashMap<String,String>();
	
	/**
	 * path pattern list for rules
	 */
	private static List<PathPattern> routeRules = new ArrayList<PathPattern>();
	
	static{
		String[] rules = ConfigHelper.getStringArray("path_resource_mapping/rule");
		if(rules != null){
			for(String rule:rules){
				attach(rule);
			}
		}
		logger.info("load rules:{}",rules);
	}
	
	/**
	 * attach route rules
	 * @param pathTemplate
	 * @param resource
	 */
	public static void attach(String rule) {
		String[] ruleInfo = rule.split(" ");
		routeMap.put(ruleInfo[0].trim(), ruleInfo[1].trim());
		routeRules.add(new PathPattern(ruleInfo[0].trim()));
		Collections.sort(routeRules);
	}
	
	/**
	 * locate resource by uri
	 * @param request
	 * @return
	 */
	public static Class locate(String path, Map<String,Object> params) {
		String pathTemplate = matchPath(path,params);
		String klassStr = routeMap.get(pathTemplate);
		if(StringUtil.isNullOrBlank(klassStr)){
			return null;
		}
		Class klass = null;
		try {
			klass = Class.forName(klassStr);
		} catch (ClassNotFoundException e) {
			logger.error("load class fail",e);
		}
		return klass;
	}

	/**
	 * match and parse uri path
	 * @param path
	 * @param urlParams
	 * @return
	 */
	private static String matchPath(String path, Map<String,Object> params){
		String target = "";	
		for(PathPattern p:routeRules){
			Matcher matcher = Pattern.compile(p.getPattern()).matcher(path);
			if(matcher.matches()){
				target = p.getPath();
				if(p.getParamNames() != null && p.getParamNames().size()>0){
					for(int i=0;i<p.getParamNames().size();i++){
						params.put(p.getParamNames().get(i), matcher.group(i+1));
					}
				}
				break;
			}
		}
		return target;
	}
	
}
